package ui;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import upload.SendToHost;
import upload.UploadEngine;
import upload.UploadInfoBean;
import util.Utility;
import download.DownloadEngine;
import download.DownloadInfoBean;


public class FileUploadUI {

	private Combo serverList;
	private Table tblFileList;
	private Table downFileTable;
	private Table table;
	protected Shell shell;
	protected static final String SEND_FILE_SUCCESS = "\u4E0A\u4F20\u6587\u4EF6\u5B8C\u6BD5!";
	protected static final String SEND_FILE_ERROR = "\u4E0A\u4F20\u6587\u4EF6\u51FA\u9519!";
	protected static final String DOWN_FILE_ERROR = "\u4E0B\u8F7D\u6587\u4EF6\u5931\u8D25!";
	protected static final String DOWN_FILE_SUCCESS = "\u4E0B\u8F7D\u6587\u4EF6\u6210\u529F!";
	protected static final String FILE_NOT_UPLOAD_SUCCESS = "\u6587\u4EF6\u4E0D\u5B8C\u6574!";
	public static String path = "/FileServer";
	public static String  host = "127.0.0.1";
	private java.util.List<String[]> serverListData;
	private ExecutorService executorService = null;
	private static final String CONFIG_FILE_NAME = "config.ini";
	private UpdateFileListThread updateFileListThread = null;
	private Label statelabel;

	/**
	 * Launch the application
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			FileUploadUI window = new FileUploadUI();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void loadConfig(){
		serverListData = new java.util.Vector<String[]>();
		File file = new File(CONFIG_FILE_NAME);
		boolean flag = false;
		if(file.exists()){
			BufferedReader br = null;
			try {
				br = new BufferedReader(new FileReader(file));
				while(true){
					String[] svr = new String[2];
					svr[1] = br.readLine();
					svr[0] = br.readLine();
					if(svr[1]==null||svr[0]==null)
						break;
					serverListData.add(svr);
					flag = true;
				}
			} catch (Exception e) {
			} finally {
				try {
					br.close();
				} catch (Exception e) {
				}
			}
		}
		if(!flag){
			String[] svr = new String[2];
			svr[0] = "/FileServer";
			svr[1] = "127.0.0.1";
			serverListData.add(svr);
		}
		String[] svr = serverListData.get(0);
		host = svr[1];
		path = svr[0];
	}
	
	/**
	 * Open the window
	 */
	public void open() {
		loadConfig();
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 3);
		final Display display = Display.getDefault();
		createContents();
		updateFileListThread = new UpdateFileListThread();
		updateFileListThread.start();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		executorService.shutdown();
		executorService.shutdownNow();
		if(updateFileListThread.isAlive()){
			updateFileListThread.stop();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setLayout(new GridLayout());
		shell.setSize(531, 322);
		shell.setText("File Upload/Download");

		serverList = new Combo(shell, SWT.READ_ONLY);
		final GridData gd_serverList = new GridData(SWT.FILL, SWT.CENTER, true, false);
		serverList.setLayoutData(gd_serverList);
		for(int i=0,len=serverListData.size();i<len;i++){
			String[] svr = serverListData.get(i);
			serverList.add(svr[1]+" "+svr[0]);
		}
		serverList.select(0);
		serverList.addSelectionListener(new SelectionListener(){
			public void widgetDefaultSelected(SelectionEvent arg0) {
			}
			public void widgetSelected(SelectionEvent arg0) {
				int index = serverList.getSelectionIndex();
				String[] svr = serverListData.get(index);
				host = svr[1];
				path = svr[0];
				if(updateFileListThread.isAlive()){
					updateFileListThread.stop();
				}
				updateFileListThread = new UpdateFileListThread();
				updateFileListThread.start();
			}
		});

		final TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
		tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		final TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
		tabItem.setText("\u4E0A\u4F20");

		final Composite composite = new Composite(tabFolder, SWT.NONE);
		composite.setLayout(new GridLayout());
		tabItem.setControl(composite);

		final Composite composite_1 = new Composite(composite, SWT.NONE);
		final GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		composite_1.setLayout(gridLayout);

		final Button btnSendFile = new Button(composite_1, SWT.NONE);
		btnSendFile.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog fileselect=new FileDialog(getShell(), SWT.SINGLE);
                fileselect.setFilterNames(new String[]{"\u6240\u6709\u6587\u4ef6"});
                fileselect.setFilterExtensions(new String[]{"*.*"});
                String url = fileselect.open();
                if(url!=null){
                	File file = new File(url);
                	if(file.exists()){
                		TableItem newItemTableItem = new TableItem(table, SWT.BORDER);
                		UploadInfoBean uib = new UploadInfoBean(file.getAbsolutePath(),file.getName(),10);
                		try{
                			UploadEngine ue = new UploadEngine(uib,newItemTableItem);
                			ue.start();
                		}catch(Exception ex){
                			System.err.print(ex.getMessage());
                		}
                	}
                }
			}
		});
		btnSendFile.setText("\u9009\u62E9\u6587\u4EF6\u4E0A\u5B58...");

		final Button btnClearFile = new Button(composite_1, SWT.NONE);
		btnClearFile.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				Display.getDefault().syncExec(new Runnable(){

					public void run() {
						java.util.List<Integer> list = new LinkedList<Integer>();
						TableItem[] tableItems = table.getItems();
						for(int i=0,len=tableItems.length;i<len;i++){
							if(tableItems[i].getText(2).equals(SEND_FILE_SUCCESS)){
								list.add(i);
							}
						}
						int[] index = new int[list.size()];
						for(int i=0,len=list.size();i<len;i++){
							index[i]=list.get(i);
						}
						table.remove(index);
					}}
				);
			}
		});
		btnClearFile.setText("\u6E05\u9664\u4E0A\u4F20\u6210\u529F\u7684\u6587\u4EF6");

		table = new Table(composite, SWT.FULL_SELECTION | SWT.BORDER);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		DropTarget dropTarget = new DropTarget(table,DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);
		dropTarget.setTransfer(new Transfer[] {FileTransfer.getInstance()});
		dropTarget.addDropListener(new FileDropTargetListener(this));
		
		final TableColumn newColumnTableColumn = new TableColumn(table, SWT.NONE);
		newColumnTableColumn.setWidth(224);
		newColumnTableColumn.setText("\u6587\u4EF6\u540D");

		final TableColumn newColumnTableColumn_2 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_2.setWidth(84);
		newColumnTableColumn_2.setText("\u5927\u5C0F");

		final TableColumn newColumnTableColumn_7 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_7.setWidth(89);
		newColumnTableColumn_7.setText("速度");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_1.setWidth(91);
		newColumnTableColumn_1.setText("\u8FDB\u5EA6");

		final TabItem tabItem_1 = new TabItem(tabFolder, SWT.NONE);
		tabItem_1.setText("\u4E0B\u8F7D");

		final Composite composite_2 = new Composite(tabFolder, SWT.NONE);
		final GridLayout gridLayout_1 = new GridLayout();
		composite_2.setLayout(gridLayout_1);
		tabItem_1.setControl(composite_2);

		final Composite composite_3 = new Composite(composite_2, SWT.NONE);
		final GridData gd_composite_3 = new GridData();
		composite_3.setLayoutData(gd_composite_3);
		final GridLayout gridLayout_2 = new GridLayout();
		gridLayout_2.numColumns = 2;
		composite_3.setLayout(gridLayout_2);

		final Button button = new Button(composite_3, SWT.NONE);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if(updateFileListThread.isAlive()){
					updateFileListThread.stop();
				}
				updateFileListThread = new UpdateFileListThread();
				updateFileListThread.start();
			}
		});
		button.setText("\u66F4\u65B0\u6587\u4EF6\u5217\u8868");

		statelabel = new Label(composite_3, SWT.NONE);
		statelabel.setText("           ");
		final GridData gd_label = new GridData(SWT.FILL, SWT.CENTER, false, false);
		gd_label.widthHint = 212;
		statelabel.setLayoutData(gd_label);

		final SashForm sashForm = new SashForm(composite_2, SWT.NONE);
		sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		final Composite composite_4 = new Composite(sashForm, SWT.NONE);
		final GridLayout gridLayout_3 = new GridLayout();
		gridLayout_3.verticalSpacing = 0;
		gridLayout_3.marginWidth = 0;
		gridLayout_3.marginHeight = 0;
		gridLayout_3.numColumns = 2;
		composite_4.setLayout(gridLayout_3);

		tblFileList = new Table(composite_4, SWT.FULL_SELECTION | SWT.BORDER);
		tblFileList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		tblFileList.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(MouseEvent e) {
				downFile(tblFileList.getSelectionIndex());
			}
		});
		tblFileList.setLinesVisible(true);
		tblFileList.setHeaderVisible(true);

		final TableColumn newColumnTableColumn_6 = new TableColumn(tblFileList, SWT.NONE);
		newColumnTableColumn_6.setWidth(92);
		newColumnTableColumn_6.setText("\u6587\u4EF6\u540D");

		final Composite composite_5 = new Composite(composite_4, SWT.NONE);
		composite_5.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
		final GridLayout gridLayout_4 = new GridLayout();
		gridLayout_4.verticalSpacing = 3;
		gridLayout_4.marginWidth = 0;
		gridLayout_4.marginHeight = 0;
		gridLayout_4.horizontalSpacing = 0;
		composite_5.setLayout(gridLayout_4);

		final Button delBtn = new Button(composite_5, SWT.NONE);
		delBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				delFile(tblFileList.getSelectionIndex());
			}
		});
		delBtn.setText("\u5220\u9664");

		final Button downBtn = new Button(composite_5, SWT.NONE);
		downBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				downFile(tblFileList.getSelectionIndex());
			}
		});
		downBtn.setText("\u4e0b\u8f7d");

		downFileTable = new Table(sashForm, SWT.FULL_SELECTION | SWT.BORDER);
		downFileTable.setLinesVisible(true);
		downFileTable.setHeaderVisible(true);

		final TableColumn newColumnTableColumn_3 = new TableColumn(downFileTable, SWT.NONE);
		newColumnTableColumn_3.setWidth(100);
		newColumnTableColumn_3.setText("\u6587\u4EF6\u540D");

		final TableColumn newColumnTableColumn_4 = new TableColumn(downFileTable, SWT.NONE);
		newColumnTableColumn_4.setWidth(100);
		newColumnTableColumn_4.setText("速度");

		final TableColumn newColumnTableColumn_5 = new TableColumn(downFileTable, SWT.NONE);
		newColumnTableColumn_5.setWidth(100);
		newColumnTableColumn_5.setText("\u8FDB\u5EA6");
		sashForm.setWeights(new int[] {183, 257 });
	}

	protected Shell getShell(){
		return this.shell;
	}
	
	public void sendFile(File file, TableItem newItemTableItem){
		UploadInfoBean uib = new UploadInfoBean(file.getAbsolutePath(),file.getName(),10);
		try{
			UploadEngine ue = new UploadEngine(uib,newItemTableItem);
			ue.start();
		}catch(Exception e){
			System.err.print(e.getMessage());
		}
	}
	
	
	
	protected class UpdateFileListThread extends Thread {
		public void run() {
			//FIXME
			String urlStr = path + "/Server?type=list";
			try{
				Display.getDefault().syncExec(new Runnable(){
					public void run() {
						statelabel.setText("\u66f4\u65b0\u6587\u4ef6\u5217\u8868\u4e2d...");
						tblFileList.removeAll();
					}
				});
				SendToHost sth = new SendToHost(host,urlStr);
				String sb = sth.send();
				sb = java.net.URLDecoder.decode(sb,"UTF-8");
				String[] files = sb.split("\\|");
				for(int i=0,len=files.length;i<len;i++){
					if(files[i]!=null&&files[i].length()!=0){
						String name = files[i];
						Display.getDefault().syncExec(new UpdateFileListItem(tblFileList, name));
					}
				}
				if(files.length==0){
					Display.getDefault().syncExec(new Runnable(){
						public void run() {
							statelabel.setText("\u6587\u4ef6\u5217\u8868\u4e3a\u7a7a!");
						}
					});
				}else{
					Display.getDefault().syncExec(new Runnable(){
						public void run() {
							statelabel.setText("");
						}
					});
				}
			}catch(Exception ex){
				Display.getDefault().syncExec(new Runnable(){
    				public void run() {
    					statelabel.setText("\u66f4\u65b0\u5217\u8868\u5931\u8d25");
    					tblFileList.removeAll();
    				}
    			});
			}
		}
	}
	
	protected class UpdateTableItem implements Runnable {
		
		TableItem newItemTableItem;
		String[] s;
		
		public UpdateTableItem(TableItem newItemTableItem, String...s){
			this.newItemTableItem = newItemTableItem;
			this.s = s;
		}
		
		public void run() {
			for(int i=0,len=s.length;i<len;i++){
				if(s[i]!=null){
					newItemTableItem.setText(i,s[i]);
				}
			}
		}
		
	}
	
	protected class UpdateFileListItem implements Runnable {
		
		String s;
		Table table;
		
		public UpdateFileListItem(Table table, String s){
			this.s = s;
			this.table = table;
		}
		
		public void run() {
			TableItem newItemTableItem = new TableItem(table, SWT.BORDER);
			newItemTableItem.setText(0, s);
		}
		
	}
	
	protected static String getFileSizeString(double fileSize){
		if(fileSize<1024.0){
			return String.format("%.2f bytes", fileSize);
		}
		fileSize = fileSize/1024.0;
		if(fileSize<1024.0){
			return String.format("%.2f KB", fileSize);
		}
		fileSize = fileSize/1024.0;
		return String.format("%.2f MB", fileSize);
	}
	

	public Table getUploadFileTable() {
		return table;
	}
	
	private void downFile(int si){
		if(si>=0){
			TableItem ti = tblFileList.getItem(si);
			FileDialog fileselect=new FileDialog(getShell(), SWT.SINGLE | SWT.SAVE);
			fileselect.setFileName(ti.getText(0));
            fileselect.setFilterNames(new String[]{"\u6240\u6709\u6587\u4ef6"});
            fileselect.setFilterExtensions(new String[]{"*.*"});
            String url = fileselect.open();
            if(url!=null){
            	File file = new File(url);
            	if(file.exists()){
            		MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION |SWT.YES | SWT.NO);
            		messageBox.setMessage("\u6587\u4ef6\u4ee5\u5b58\u5728, \u8986\u76d6\u5417?");
            		int rc = messageBox.open();
            		
            		if(rc!=SWT.YES)
            			return;
            	}
            	TableItem newItemTableItem = new TableItem(downFileTable, SWT.BORDER);
            	newItemTableItem.setText(0, ti.getText(0));
            	
            	try
        		{
            		String downloadUrl = host + path + "/file/" +  Utility.URLEncode(ti.getText(0));
            		if(!host.startsWith("http://")){
            			downloadUrl = "http://" + downloadUrl;
            		}
        			DownloadInfoBean bean = new DownloadInfoBean(downloadUrl, Utility.getFilePathWidthoutName(file), ti.getText(0), 5);
        			DownloadEngine fileFetch = new DownloadEngine(bean, newItemTableItem);
        			fileFetch.start();
        		}
        		catch (Exception e)
        		{
        			e.printStackTrace();
        		}
            }
			
		}
	}
	
	private void delFile(int si){
		if(si>=0){
			TableItem ti = tblFileList.getItem(si);
			new DelFileThread(tblFileList,ti.getText(0));
		}
	}
	
	protected class DelFileThread extends Thread {
		String encodeName = "";
		Table table;
		int index;
		public DelFileThread(Table table, String name){
			encodeName = Utility.URLEncode(name);
			this.table = table;
			this.start();
		}
		
		public void run() {
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					statelabel.setText("\u5220\u9664\u6587\u4ef6\u4e2d...");
				}
			});
			//FIXME
			String urlStr = path + "/Server?type=delete&name="+encodeName;
			try{
				Utility.send(urlStr);
				Display.getDefault().syncExec(new Runnable() {
					public void run() {
						table.remove(index);
					}
				});
			}catch(Exception ex){
				Display.getDefault().syncExec(new Runnable() {
					public void run() {
						MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR);
						messageBox.setMessage("\u5220\u9664\u6587\u4ef6\u5931\u8d25!");
						messageBox.open();
					}
				});
			}
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					statelabel.setText("");
				}
			});
		}
	}
}
